package com.holystone.splunk.app.service.impl;

import com.github.pagehelper.PageInfo;
import com.holystone.splunk.app.model.AlertVO;
import com.holystone.splunk.app.model.EventVO;
import com.holystone.splunk.app.mybatis.model.Alert;
import com.holystone.splunk.app.mybatis.model.Event;
import com.holystone.splunk.app.service.IIndexAlertService;
import com.holystone.splunk.app.service.IIndexEventService;
import com.holystone.splunk.app.utils.AlertUtils;
import com.holystone.splunk.common.SystemConstant;
import com.holystone.splunk.utils.*;
import com.splunk.FiredAlert;
import com.splunk.Job;
import com.splunk.JobResultsArgs;
import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonNode;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;

/**
 * Copyright (c) 2017, HOLYSTONE Technologies, Inc.
 * All right reserved.
 *
 * @author huyan
 * @date 2017/12/1
 * @desc:
 */
@Service(value = "indexAlertService")
public class IndexAlertServiceImpl extends SplunkIndexServiceImpl implements IIndexAlertService {

    private Logger logger = Logger.getLogger(this.getClass());
    @Resource(name = "indexEventService")
    private IIndexEventService indexEventService;



    @Override
    public void saveAlertFromFiredAlert(FiredAlert firedAlert, Set<Event> events) throws Exception {
        logger.debug(">>>>> 保存新告警数据 saveAlertFromFiredAlert()");
        if (firedAlert != null) {
            // 告警的基本属性
            AlertVO newAlert = new AlertVO();
            newAlert.setAlertSid(firedAlert.getSid());
            newAlert.setAlertName(firedAlert.getSavedSearchName());
            newAlert.setTempAlertName(AlertUtils.getAlertName(firedAlert.getSavedSearchName()));
            newAlert.setAlertType(firedAlert.getAlertType());
            newAlert.setAlertOwner(firedAlert.getMetadata().getOwner()); // 特殊
            newAlert.setAlertLevel(firedAlert.getSeverity());
            newAlert.setTriggerTime(firedAlert.getTriggerTime());
            newAlert.setCreateTime(new Date());
            if (events != null && events.size() != 0) {
                newAlert.setAlertState(1);
                newAlert.setEvents(events);
            }else {
                newAlert.setEvents(new HashSet<>());
                newAlert.setAlertState(0);
            }
            /**
             * 存告警的搜索时间段，告警结果，告警搜索语句，r_md5值，r_search值
             *
             * Splunk中时间格式：yyyy/MM/dd:HH:mm:ss （按照Splunk格式存储，方便做搜索）
             * 对告警结果进行判断，如果为table就存
             * 如果为原始日志：就不存
             */
            Job job = getService().getJob(firedAlert.getSid());
            newAlert.setEarliestTime(DateFormatUtils.date2Str(job.getEarliestTime(), "yyyy/MM/dd:HH:mm:ss"));
            newAlert.setLatestTime(DateFormatUtils.date2Str(job.getLatestTime(), "yyyy/MM/dd:HH:mm:ss"));
            newAlert.setAlertSearch(job.getSearch());
            JobResultsArgs args = new JobResultsArgs();
            args.setOutputMode(JobResultsArgs.OutputMode.JSON);
            JsonNode json = JSONUtils.jsonStr2JsonNode(StringUtils.inputStream2String(job.getResults(args)));
            JsonNode results = json.get("results");
            if (results != null && results.isArray()) {
                JsonNode jsonNode = results.get(0);
                // 原始日志
                if (jsonNode.get("_raw") != null) {
                    newAlert.setAlertResult(null);
                } else if (jsonNode.get("_raw") == null) {// 如果为null，整个results都要存
                    if (results.toString().length() < SystemConstant.MAX_SIZE) {
                        newAlert.setAlertResult(results.toString());
                    } else {
                        newAlert.setAlertResult(SystemConstant.MAX_RESULT);
                    }
                }
            } else if (results != null && !results.isArray()) {
                if (results.get("_raw") != null) {
                    newAlert.setAlertResult(null);
                } else if (results.get("_raw") == null) {
                    newAlert.setAlertResult(results.toString());
                }
            } else {
                newAlert.setAlertResult(null);
            }
            // 存md5值和search值，如果md5没有值，就sid值存到md5中
            Map<String, String> map = dealResult(json);
            if (map != null) {
                newAlert.setR_md5(map.get(SystemConstant.ALERT_MD5));
                newAlert.setR_search(map.get(SystemConstant.ALERT_SEARCH));
            } else {
                newAlert.setR_md5(firedAlert.getSid());
            }
            insertAlert2Index(newAlert);
            // 更新事件表
            if (events != null && events.size() != 0) {
                for (Event event : events) {
                    EventVO eventVO = indexEventService.getEventByEventIds(event.getEventId()+"").get(0);
                    Set<Alert> alerts = eventVO.getAlerts();
                    if (alerts == null) {
                        alerts = new HashSet<>();
                    }
                    alerts.add(AlertVO.getAlert(newAlert));
                    eventVO.setAlerts(alerts);
                    indexEventService.insertEvent2Index(eventVO);
                }
            }
        }
        logger.debug("<<<<< 保存新告警数据 saveAlertFromFiredAlert()");
    }

    @Override
    public void insertAlert2Index(AlertVO alert) throws IOException {
        logger.debug(">>>>> 插入告警数据 insertAlert2Index() alertSid:" + alert.getAlertSid());
        String alertJson = JSONUtils.javaBean2Json(alert);
        insertData2Index(SystemConstant.SPLUNK_INDEX, SystemConstant.SOURCETYPE_ALERT, alertJson);
        logger.debug("<<<<< 插入告警数据 insertAlert2Index() alertSid:" + alert.getAlertSid());
    }

    @Override
    public List<AlertVO> getAlertsBySids(String alertSids) throws IOException {
        logger.debug(">>>>> 根据sids字符串获取多个告警 getAlertsBySids() alertSids:" + alertSids);
        if (alertSids == null || alertSids == "") {
            return null;
        }
        // 拼接query
        String query = "search index=" + SystemConstant.SPLUNK_INDEX +
                " sourcetype=" + SystemConstant.SOURCETYPE_ALERT +
                " | dedup alertSid" +
                " | where 1=1 and";
        String[] sids = alertSids.split(",");
        for (String sid : sids) {
            query += " alertSid=\"" + sid + "\" or ";
        }
        if (sids.length != 0) {
            query = query.substring(0, query.length() - 3);
        }
        // 查询
        List<JsonNode> jsonList = getDataFromIndex(query, null, null, null, null);
        // 封装返回结果
        if (jsonList == null || jsonList.size() == 0) {
            return null;
        }
        List<AlertVO> voList = new ArrayList<>();
        for (JsonNode jsonNode : jsonList) {
            /*
              使用 transaction函数，可能一条记录会返回多个对象，用"\n"分割，取最新的对象
             */
            String[] voArr = jsonNode.asText().split("\n");
            voList.add(JSONUtils.jsonStr2JavaBean(voArr[voArr.length - 1], AlertVO.class));
        }
        logger.debug("<<<<< 根据sids字符串获取多个告警 getAlertsBySids() alertSids:" + alertSids);
        return voList;
    }

    @Override
    public List<String> getExistsAlertNames() throws IOException {
        logger.debug(">>>>> 获取存在的告警名称集合 getExistsAlertNames()");
        List<String> names=null;
        try{
            // 初始化--必须
            EHCacheUtil.initCacheManager();
            //缓存60分钟
            EHCacheUtil.initCache(EHCacheConfig.PROJECR_YONGYUAN_CACHE,EHCacheConfig.PROJECR__CACHE_TIME_60);
            Object obj= EHCacheUtil.get(EHCacheConfig.PROJECR_YONGYUAN_CACHE_ALERT_NAME_KEY);
            if(obj==null){
                names = getDIYStatisticaData(SystemConstant.SPLUNK_INDEX, SystemConstant.SOURCETYPE_ALERT, "alertName");
                EHCacheUtil.put(EHCacheConfig.PROJECR_YONGYUAN_CACHE_ALERT_NAME_KEY, names);
            }else{
                names =(List<String>)obj;
            }
        }catch (Exception e){
            logger.debug(e,e);
        }
        logger.debug("<<<<< 获取存在的告警名称集合 getExistsAlertNames()");
        return names;
    }

    @Override
    public PageInfo<AlertVO> getAlertsPageInfo(String pageNo, String pageSize, AlertVO conditions) throws IOException, ParseException {
        logger.debug(">>>>> 获取告警分页数据 getAlertsPageInfo()");
        Integer no = pageNo == null ? SystemConstant.DEFAULT_PAGE_NUM : Integer.parseInt(pageNo);
        Integer size = pageSize == null ? SystemConstant.DEFAULT_PAGE_SIZE : Integer.parseInt(pageSize);

        List<AlertVO> voList = getAlertsByConditions(no, size, conditions);
        Integer totalCount = getAlertsTotalByCondtions(conditions);
        Integer totalPages = totalCount%size == 0 ? totalCount/size : totalCount/size + 1;
        PageInfo<AlertVO> info = new PageInfo<>();
        info.setList(voList);
        info.setPageNum(no);
        info.setPageSize(size);
        info.setTotal(totalCount);
        info.setPages(totalPages);
        logger.debug("<<<<< 获取告警分页数据 getAlertsPageInfo()");
        return info;
    }

    @Override
    public List<AlertVO> getAlertsByConditions(Integer pageNo, Integer pageSize, AlertVO conditions) throws IOException, ParseException {
        logger.debug(">>>>> 获取满足条件的告警列表 getAlertsByCondtions()");
        //拼接query
        String query = "search index=" + SystemConstant.SPLUNK_INDEX +
                " sourcetype=" + SystemConstant.SOURCETYPE_ALERT +
                " | dedup alertSid" +
                " | where 1=1";
        if (conditions != null) {
            if (conditions.getAlertName() != null && conditions.getAlertName() != "") {
                query += " and like(alertName, \"%"+ conditions.getAlertName()+"%\")";
            }
            if (conditions.getAlertLevel() != null) {
                query += " and alertLevel=" + conditions.getAlertLevel();
            }
            if (conditions.getKeySearch() != null && conditions.getKeySearch() != "") {
                query += "and like(alertResult, \"%" + conditions.getKeySearch() + "%\")";
            }
        }
        query += "| transaction r_md5 maxspan=1d";
        //查询数据
        Date earliest = null;
        Date latest = null;
        if (conditions.getEarliestTime() != null && !"".equals(conditions.getEarliestTime())) {
            earliest = DateFormatUtils.str2Date(conditions.getEarliestTime()+" 00:00:00");
        }
        if (conditions.getLatestTime() != null && !"".equals(conditions.getLatestTime())) {
            latest = DateFormatUtils.str2Date(conditions.getLatestTime()+" 23:59:59");
        }
        List<JsonNode> jsonList = getDataFromIndex(query, pageNo, pageSize, earliest, latest);
        //封装返回数据
        if (jsonList == null) {
            return null;
        }
        List<AlertVO> voList = new ArrayList<>();
        /*
            dedup 关键字会依据alertSid取最新记录
            transaction 关键字会将相同值的记录聚合在一起
         */
        Map<String, AlertVO> map = new HashMap<>();
        for (JsonNode jsonNode : jsonList) {
            map.clear();
            AlertVO vo = null;
            String[] JsonArr = jsonNode.asText().split("\n");
            for (String json : JsonArr) {
                vo = JSONUtils.jsonStr2JavaBean(json, AlertVO.class);
                map.put(vo.getAlertSid(), vo);
            }
            vo.setAlertCount(map.size());
            voList.add(vo); // 只取最新值，哪怕是多个告警
        }
        logger.debug("<<<<< 获取满足条件的告警列表 getAlertsByCondtions()");
        return voList;
    }

    @Override
    public Integer getAlertsTotalByCondtions(AlertVO conditions) throws IOException, ParseException {
        logger.debug(">>>>> 获取符合条件的告警的总数 getAlertsTotalByConditions()");
        // 封装query
        String query = "search index=" + SystemConstant.SPLUNK_INDEX +
                " sourcetype=" + SystemConstant.SOURCETYPE_ALERT +
                " | dedup alertSid" +
                " | where 1=1";
        if (conditions != null) {
            if (conditions.getAlertName() != null && conditions.getAlertName() != "") {
                query += " and like(alertName, \"%"+ conditions.getAlertName()+"%\")";
            }
            if (conditions.getAlertLevel() != null) {
                query += " and alertLevel=" + conditions.getAlertLevel();
            }
            if (conditions.getKeySearch() != null && !"".equals(conditions.getKeySearch()) ) {
                query += "and like(alertResult, \"%" + conditions.getKeySearch() + "%\")";
            }
        }
        query += "| transaction r_md5  maxspan=1d| stats count as totalCount";
        // 查询
        Date earliest = null;
        Date latest = null;
        if (conditions.getEarliestTime() != null && !"".equals(conditions.getEarliestTime())) {
            earliest = DateFormatUtils.str2Date(conditions.getEarliestTime()+" 00:00:00");
        }
        if (conditions.getLatestTime() != null && !"".equals(conditions.getLatestTime() )) {
            latest = DateFormatUtils.str2Date(conditions.getLatestTime()+" 23:59:59");
        }
        Integer totalCount = getDIYTotalCount(query, "totalCount", earliest, latest);
        logger.debug("<<<<< 获取符合条件的告警的总数 getAlertsTotalByConditions()");
        return totalCount;
    }


    @Override
    public PageInfo<AlertVO> getAlertPageInfoByMD5(String pageNo, String pageSize, AlertVO conditions) throws IOException, ParseException {
        logger.debug(">>>>> 获取r_md5值相同的告警信息 getAlertPageInfoByMD5() md5:" + conditions.getR_md5());
        Integer no = pageNo == null ? SystemConstant.DEFAULT_PAGE_NUM : Integer.parseInt(pageNo);
        Integer size = pageSize == null ? SystemConstant.DEFAULT_PAGE_SIZE : Integer.parseInt(pageSize);

        List<AlertVO> voList = getAlertsByR_MD5(no, size, conditions);
        Integer totalCount = getAlertsTotalByR_MD5(conditions);
        Integer totalPages = totalCount%size == 0 ? totalCount/size : totalCount/size + 1;
        PageInfo<AlertVO> info = new PageInfo<>();
        info.setList(voList);
        info.setPageNum(no);
        info.setPageSize(size);
        info.setTotal(totalCount);
        info.setPages(totalPages);
        logger.debug("<<<<< 获取r_md5值相同的告警信息 getAlertPageInfoByMD5() md5:" + conditions.getR_md5());
        return info;
    }

    @Override
    public List<AlertVO> getAlertsByR_MD5(Integer pageNo, Integer pageSize, AlertVO conditions) throws IOException, ParseException {
        logger.debug(">>>>> 根据r_md5查询告警信息 getAlertsByR_MD5()");
        // 拼接查询
        String query = "search index=" + SystemConstant.SPLUNK_INDEX +
                " sourcetype=" + SystemConstant.SOURCETYPE_ALERT +
                " | dedup alertSid" +
                " | where 1=1";
        if (conditions != null) {
            if (conditions.getAlertName() != null && conditions.getAlertName() != "") {
                query += " and like(alertName, \"%"+ conditions.getAlertName()+"%\")";
            }
            if (conditions.getAlertLevel() != null) {
                query += " and alertLevel=" + conditions.getAlertLevel();
            }
            if (conditions.getR_md5() != null && conditions.getR_md5() != "") {
                query += " and r_md5=\"" + conditions.getR_md5() + "\"";
            }
        }
        // 查询数据
        Date earliest = null;
        Date latest = null;
        if (conditions.getEarliestTime() != null && conditions.getEarliestTime() != "") {
            earliest = DateFormatUtils.str2Date(conditions.getEarliestTime());
        }
        if (conditions.getLatestTime() != null && conditions.getLatestTime() != "") {
            latest = DateFormatUtils.str2Date(conditions.getLatestTime());
        }
        List<JsonNode> jsonList = getDataFromIndex(query, pageNo, pageSize, earliest, latest);
        //封装返回数据
        if (jsonList == null) {
            return null;
        }
        List<AlertVO> voList = new ArrayList<>();
        for (JsonNode jsonNode : jsonList) {
            AlertVO vo = JSONUtils.jsonStr2JavaBean(jsonNode.asText(), AlertVO.class);
            voList.add(vo);

        }
        logger.debug("<<<<< 根据r_md5查询告警信息 getAlertsByR_MD5()");
        return voList;
    }

    @Override
    public Integer getAlertsTotalByR_MD5(AlertVO conditions) throws IOException, ParseException {
        logger.debug(">>>>> 获取R_MD5总数量 getAlertsTotalByR_MD5()");
        // 封装query
        String query = "search index=" + SystemConstant.SPLUNK_INDEX +
                " sourcetype=" + SystemConstant.SOURCETYPE_ALERT +
                " | dedup alertSid" +
                " |where 1=1";
        if (conditions != null) {
            if (conditions.getAlertName() != null && conditions.getAlertName() != "") {
                query += " and like(alertName, \"%"+ conditions.getAlertName()+"%\")";
            }
            if (conditions.getAlertLevel() != null) {
                query += " and alertLevel=" + conditions.getAlertLevel();
            }
            if (conditions.getR_md5() != null && conditions.getR_md5() != "") {
                query += " and r_md5=\"" + conditions.getR_md5() + "\"";
            }
        }
        query += "| stats count as totalCount";
        // 查询
        Date earliest = null;
        Date latest = null;
        if (conditions.getEarliestTime() != null && conditions.getEarliestTime() != "") {
            earliest = DateFormatUtils.str2Date(conditions.getEarliestTime());
        }
        if (conditions.getLatestTime() != null && conditions.getLatestTime() != "") {
            latest = DateFormatUtils.str2Date(conditions.getLatestTime());
        }
        Integer totalCount = getDIYTotalCount(query, "totalCount", earliest, latest);
        logger.debug("<<<<< 获取R_MD5总数量 getAlertsTotalByR_MD5()");
        return totalCount;
    }

    @Override
    public void unLinkEvents(String alertSid, String eventIds) throws IOException {
        logger.debug(">>>>> 解绑告警-事件关联关系 unLinkEvents()");
        /**
         * 解绑告警-事件关联关系
         * 1.解绑告警中的事件，需要考虑解绑之后告警中是否还包含事件，如果不包含，将告警状态置为0
         * 2.解绑事件中的告警
         */
        //1.
        String[] split = eventIds.split(",");
        AlertVO alert = getAlertsBySids(alertSid).get(0);
        Set<Event> events = alert.getEvents();
        if (events != null) {
            Iterator<Event> it = events.iterator();
            while (it.hasNext()) {
                Event next = it.next();
                for (String eventId : split) {
                    if (eventId.equals(next.getEventId()+"")) {
                        it.remove();
                    }
                }
            }
            if (events.size() == 0) {
                alert.setAlertState(0);
            }
            insertAlert2Index(alert);
        }
        //2.
        List<EventVO> eventVOList = indexEventService.getEventByEventIds(eventIds);
        for (EventVO vo : eventVOList) {
            Set<Alert> alerts = vo.getAlerts();
            Iterator<Alert> it = alerts.iterator();
            while (it.hasNext()) {
                Alert next = it.next();
                if (alertSid.equals(next.getAlertSid())) {
                    it.remove();
                }
            }
            indexEventService.insertEvent2Index(vo);
        }
        logger.debug("<<<<< 解绑告警-事件关联关系 unLinkEvents()");
    }

    @Override
    public Map<String, List<AlertVO>> getAlertDataBySid(String alertSid) throws IOException, ParseException {
        logger.debug(">>>>> 获取日志数据 getAlertDataBySid() alertSid:" + alertSid);
        Map<String, List<AlertVO>> voMap = new LinkedHashMap<>();
        /**
         * 封装告警的返回数据：有两种返回格式
         *      原始日志：eventJson
         *      table表格：tableJson
         * 告警类Alert中封装的有告警结果alertResult，这个属性只会存储告警结果为table的，原始日志不存
         * 根据这个来判断前台展示效果
         *      1.如果alertResult为null，前台只展示原始日志
         *      2.如果alertResult不为null，前台展示table表格和原始日志
         */
        AlertVO alert = getAlertsBySids(alertSid).get(0);
        String resultStr = alert.getAlertResult();
        Date earliest = DateFormatUtils.str2Date(alert.getEarliestTime(), "yyyy/MM/dd:HH:mm:ss");
        Date latest = DateFormatUtils.str2Date(alert.getLatestTime(), "yyyy/MM/dd:HH:mm:ss");
        if (resultStr != null && resultStr != "" && !SystemConstant.MAX_RESULT.equals(resultStr)) {
            // table看情况展示
            JsonNode result = JSONUtils.jsonStr2JsonNode(resultStr);
            List<AlertVO> voList = formatResult(result);
            for (AlertVO vo : voList) {
                vo.setAlertName(alert.getAlertName());
            }
            voMap.put("tableJson", voList);
        }
        // 告警结果过长，重新查
        else if (SystemConstant.MAX_RESULT.equals(resultStr)) {
            JsonNode result = search(alert.getAlertSearch(), null, null, earliest, latest);
            List<AlertVO> voList = formatResult(result);
            for (AlertVO vo : voList) {
                vo.setAlertName(alert.getAlertName());
            }
            voMap.put("tableJson", voList);
        }
        // 原始日志必须展示
        String query = PropertiesUtils.readValue(alert.getAlertName().trim());
        if (query != null && query != "") {
            query = query.replaceAll("alertSid", alert.getAlertSid());
            List<JsonNode> jsonList = getDataFromIndex(query, null, null, earliest, latest);
            List<AlertVO> voList = new ArrayList<>();
            AlertVO vo = null;
            for (JsonNode jsonNode : jsonList) {
                vo = new AlertVO();
                vo.setAlertName(alert.getAlertName());
                vo.setAlertData(jsonNode.toString());
                voList.add(vo);
            }
            voMap.put("eventJson", voList);
        }
        logger.debug("<<<<< 获取日志数据 getAlertDataBySid() alertSid:" + alertSid);
        return voMap;
    }

    @Override
    public List<AlertVO> getAlertsByEvent(Integer pageNo, Integer pageSize, Set<Alert> alerts) throws IOException {
        logger.debug(">>>>> 获取告警列表 getAlertsByEvent()");
        // 拼接query
        String query = "search index=" + SystemConstant.SPLUNK_INDEX +
                " sourcetype=" + SystemConstant.SOURCETYPE_ALERT +
                " | dedup alertSid" +
                " |where ";
        for (Alert vo : alerts) {
            query += " alertSid=\"" + vo.getAlertSid() + "\" or ";
        }
        if (alerts != null && alerts.size() != 0) {
            query = query.substring(0, query.length() - 3);
        }
        query += "| transaction r_md5 maxspan=1d";
        // 查询数据
        List<JsonNode> jsonList = getDataFromIndex(query, pageNo, pageSize, null, null);
        // 封装返回数据
        if (jsonList == null) {
            return null;
        }
        List<AlertVO> voList = new ArrayList<>();
        Map<String, AlertVO> map = new HashMap<>(); // 使用map来作为辨别是否是同一个告警(sid相同，即告警相同)
        for (JsonNode jsonNode : jsonList) {
            map.clear();
            /**
             * 使用 transaction函数，可能一条记录会返回多个对象，用" "分割，取最新的对象
             */
            String[] split = jsonNode.asText().split("\n");
            AlertVO vo = null;
            for (String jsonStr : split) {
                vo = JSONUtils.jsonStr2JavaBean(jsonStr, AlertVO.class);
                map.put(vo.getAlertSid(), vo);
            }
            vo.setAlertCount(map.size());
            voList.addAll(map.values());
        }
        logger.debug("<<<<< 获取告警列表 getAlertsByEvent()");
        return voList;
    }

    @Override
    public Integer getAlertTotalCountByEvent(Set<Alert> alerts) throws IOException {
        logger.debug(">>>>> 获取告警总数量 getAlertTotalCountByEvent()");
        // 拼接query
        String query = "search index=" + SystemConstant.SPLUNK_INDEX +
                " sourcetype=" + SystemConstant.SOURCETYPE_ALERT +
                " | dedup alertSid" +
                " | where 1 =1 and";
        for (Alert vo : alerts) {
            query += " alertSid=\"" + vo.getAlertSid() + "\" or ";
        }
        if (alerts != null && alerts.size() != 0) {
            query = query.substring(0, query.length() - 3);
        }
        query += "| stats count as totalCount";
        // 查询数据
        Integer totalCount = getDIYTotalCount(query, "totalCount", null, null);
        logger.debug("<<<<< 获取告警总数量 getAlertTotalCountByEvent()");
        return totalCount;
    }

    private List<AlertVO> formatResult(JsonNode jsonNode) {
        AlertVO vo = null;
        List<AlertVO> voList = new ArrayList<>();
        Map<String, Object> map = null;
        if (jsonNode != null) {
            if (jsonNode.isArray()) {
                for (int i = 0; i < jsonNode.size(); i++) {
                    JsonNode json = jsonNode.get(i);
                    vo = new AlertVO();
                    map = new HashMap<>();
                    Iterator<String> fieldNames = json.getFieldNames();
                    while (fieldNames.hasNext()) {
                        String name = fieldNames.next();
                        if (SystemConstant.ALERT_MD5.equals(name) || SystemConstant.ALERT_SEARCH.equals(name)) {
                            continue;
                        }
                        JsonNode value = json.get(name);
                        map.put(name, value.toString());
                    }
                    vo.setMap(map);
                    voList.add(vo);
                }
            }else {
                vo = new AlertVO();
                map = new HashMap<>();
                Iterator<String> fieldNames = jsonNode.getFieldNames();
                while (fieldNames.hasNext()) {
                    String name = fieldNames.next();
                    if (SystemConstant.ALERT_MD5.equals(name) || SystemConstant.ALERT_SEARCH.equals(name)) {
                        continue;
                    }
                    JsonNode value = jsonNode.get(name);
                    map.put(name, value.toString());
                }
                vo.setMap(map);
                voList.add(vo);
            }
        }
        return voList;
    }

    /**
     * 通过result获取md5值和search语句
     * @return
     * @throws Exception
     */
    private Map<String, String> dealResult(JsonNode json) throws Exception {
        Map<String, String> map = new HashMap<>();
        List<String> md5List = new ArrayList<>();

        JsonNode result = json.get("results");
        if (result != null) {

            StringBuilder searchBuilder = new StringBuilder();
            if (result.isArray()) {
                for(int i = 0, len=result.size(); i < len; i++) {
                    JsonNode jsonNode = result.get(i);
                    JsonNode md5 = jsonNode.get(SystemConstant.ALERT_MD5);
                    if (md5 == null) {
                        return null;
                    }else {
                        md5List.add(md5.asText());
                        searchBuilder.append(jsonNode.get(SystemConstant.ALERT_SEARCH).asText()).append(" ");
                    }
                }
            }else {
                JsonNode md5 = result.get(SystemConstant.ALERT_MD5);
                if (md5 == null) {
                    return null;
                }else {
                    md5List.add(md5.asText());
                    searchBuilder.append(result.get(SystemConstant.ALERT_SEARCH).asText()).append(" ");
                }
            }

            Collections.sort(md5List);
            StringBuilder md5Builder = new StringBuilder();
            for (String md5 : md5List) {
                md5Builder.append(md5).append(",");
            }
            if (md5Builder.length() > 0) {
                String R_md5 = Md5Utils.EncoderByMd5(md5Builder.substring(0, md5Builder.length() - 1));
                map.put(SystemConstant.ALERT_MD5, R_md5);
            }
            if (searchBuilder.length() > 0) {
                String R_search = Md5Utils.EncoderByMd5(searchBuilder.substring(0, searchBuilder.length() - 1));
                map.put(SystemConstant.ALERT_SEARCH, R_search);
            }
        }
        return map;
    }

    /**
     * |metadata type=sourcetypes index=event_alert_index |search sourcetype=alert|fields recentTime| eval recentTime=strftime(recentTime,"%m/%d/%Y %H:%M:%S")
     * @return
     * @throws IOException
     */
    @Override
    public String queryEndTimeAlertData() throws IOException {
        logger.debug(">>>>> 获取告警数据中最后一条数据时间 queryEndTimeAlertData()");
        // 拼接query
        String query = "|metadata type=sourcetypes index=" + SystemConstant.SPLUNK_INDEX +
                "|search sourcetype=" + SystemConstant.SOURCETYPE_ALERT +
                " |fields recentTime";
              //  " | eval recentTime=strftime(recentTime,\"%Y-%m-%d/\")";
        // 查询数据
        String  enddate = getEnddate(query, "recentTime");
        logger.debug("<<<<< 获取告警数据中最后一条数据时间 queryEndTimeAlertData()");
        return enddate;
    }
}
